package cn.aitrox.ry.service.config.service.impl;

import cn.aitrox.ry.bean.CommonPageInfo;
import cn.aitrox.ry.bean.RespResult;
import cn.aitrox.ry.enumtype.RespCodeEnum;
import cn.aitrox.ry.service.config.dao.LesionDao;
import cn.aitrox.ry.service.config.dto.LesionDto;
import cn.aitrox.ry.service.config.dto.in.LesionCreateInDto;
import cn.aitrox.ry.service.config.dto.in.LesionEditInDto;
import cn.aitrox.ry.service.config.dto.in.LesionInDto;
import cn.aitrox.ry.service.config.entity.LesionEntity;
import cn.aitrox.ry.service.config.service.LesionService;
import cn.aitrox.ry.util.ArrayUtil;
import cn.aitrox.ry.util.BeanUtil;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class LesionServiceImpl implements LesionService {

    private static final int ROOT_LESION_PARENT_ID = 0;

    private static final String LESION_PREFIX = "ANNO";

    @Autowired
    private LesionDao lesionDao;

    @Override
    public String maxValue() {
        List<LesionEntity> allLesion = lesionDao.findAll();
        if (ArrayUtil.isEmpty(allLesion)) {
            return null;
        }

        List<Integer> maxValue = allLesion.stream().filter(x -> x.getValue().startsWith(LESION_PREFIX) && StringUtils.isNumeric(x.getValue().substring(4))).map(x -> Integer.parseInt(x.getValue().substring(4))).sorted(Comparator.reverseOrder()).limit(1).collect(Collectors.toList());
        if (ArrayUtil.isEmpty(maxValue)) {
            return null;
        }
        return LESION_PREFIX + maxValue.get(0);
    }

    @Override
    public PageInfo<LesionEntity> search(Integer page, Integer pageSize, String name, List<String> valueList) {
        String likeName = null;
        if (StringUtils.isNotEmpty(name)) {
            likeName = "%" + name + "%";
        }
        return lesionDao.search(page, pageSize, likeName, valueList, null);
    }

    @Override
    public CommonPageInfo<LesionDto> lesionGroupSearch(Integer page, Integer pageSize, String name, List<String> valueList) {
        String likeName = null;
        if (StringUtils.isNotEmpty(name)) {
            likeName = "%" + name + "%";
        }
        PageInfo<LesionEntity> pageInfo = lesionDao.search(page, pageSize, likeName, valueList, 0);
        if (ArrayUtil.isEmpty(pageInfo.getList())) {
            return new CommonPageInfo<>();
        }
        List<Integer> lessionIdList = pageInfo.getList().stream().map(LesionEntity::getId).distinct().collect(Collectors.toList());

        List<LesionEntity> childList = lesionDao.findByParenIds(lessionIdList);

        Map<Integer, List<LesionEntity>> childMap = childList.stream().collect(Collectors.groupingBy(LesionEntity::getParentId));

        List<LesionDto> list = pageInfo.getList().stream().map(x -> {
            LesionDto lesion = new LesionDto();
            BeanUtil.copy(x, lesion);

            List<LesionEntity> childListByParent = childMap.get(x.getId());
            if (!ArrayUtil.isEmpty(childListByParent)) {
                List<LesionDto> childs = childListByParent.stream().map(y -> {
                    LesionDto childLesion = new LesionDto();
                    BeanUtil.copy(y, childLesion);
                    return childLesion;
                }).collect(Collectors.toList());

                lesion.setChilds(childs);
            }

            return lesion;
        }).collect(Collectors.toList());

        return new CommonPageInfo<>(pageInfo.getTotal(), pageInfo.getPages(), list);
    }

    @Transactional
    @Override
    public RespResult edit(LesionEditInDto input) {
        LesionEntity parentLesion = lesionDao.findById(input.getId());
        if (null == parentLesion || parentLesion.getParentId() != 0) {
            RespResult.error(RespCodeEnum.NOT_EXIST);
        }

        // 校验数据是否病灶组或单个病灶名称是否存在
        if (null != input.getName() && !input.getName().equals(parentLesion.getName())) {
            LesionEntity lesionEntity = lesionDao.findByParentIdName(0, input.getName());
            if (null != lesionEntity) {
                RespResult.error("病灶名称已存在: " + input.getName());
            }
        }

        if (!ArrayUtil.isEmpty(input.getChilds())) {
            List<String> valueList = input.getChilds().stream().map(LesionInDto::getValue).collect(Collectors.toList());
            List<LesionEntity> lesionEntityList = lesionDao.findByValues(valueList);
            if (!ArrayUtil.isEmpty(lesionEntityList)) {
                List<String> existedLesionValues = lesionEntityList.stream().map(LesionEntity::getValue).collect(Collectors.toList());
                RespResult.error("病灶已存在: " + StringUtils.joinWith(",", existedLesionValues.toArray()));
            }

            List<LesionEntity> lesionEntity2Save = input.getChilds().stream().map(x -> {
                LesionEntity lesionEntity = new LesionEntity(null, parentLesion.getId(), x.getName(), x.getValue(), x.getColor(), false, null);
                return lesionEntity;
            }).collect(Collectors.toList());

            // 删除再新增
            lesionDao.deleteByParentId(parentLesion.getId());
            lesionDao.batchInsert(lesionEntity2Save);
        }

        // 更新单病灶或者病灶组的名称
        if (null != input.getName() && !input.getName().equals(parentLesion.getName())) {
            LesionEntity parent = new LesionEntity(input.getId(), null, input.getName(), null, null, null, null);
            lesionDao.updateByIdSelective(parent);
        }

        return RespResult.ok();

    }

    @Transactional
    @Override
    public RespResult create(LesionCreateInDto input) {
        List<LesionEntity> lesionListInDB = lesionDao.findByValues(Arrays.asList(input.getValue()));
        if (!ArrayUtil.isEmpty(lesionListInDB)) {
            return RespResult.secByError(RespCodeEnum.EXISTED.getCode(), "病灶编码已存在");
        }
        lesionListInDB = lesionDao.findByNames(Arrays.asList(input.getName()));
        if (!ArrayUtil.isEmpty(lesionListInDB)) {
            return RespResult.secByError(RespCodeEnum.EXISTED.getCode(), "病灶名称已存在");
        }

        LesionEntity lesion2Save = new LesionEntity(null, ROOT_LESION_PARENT_ID, input.getName(), input.getValue(), input.getColor(), input.getGroupFlag(), null);

        lesionDao.insertSelective(lesion2Save);

        List<LesionEntity> childLesion2Save = null;
        if (lesion2Save.getGroupFlag() && !ArrayUtil.isEmpty(input.getChilds())) {
            childLesion2Save = input.getChilds().stream().map(x -> {
                LesionEntity lesionEntity = new LesionEntity(null, lesion2Save.getId(), x.getName(), x.getValue(), x.getColor(), false, null);
                return lesionEntity;
            }).collect(Collectors.toList());
        }

        if (!ArrayUtil.isEmpty(childLesion2Save)) {
            lesionDao.batchInsert(childLesion2Save);
        }
        return RespResult.ok();
    }

}
